﻿/*
* Copyright (c) 2008 michiyasu wada
* http://www.seyself.com/
* 
* Distributed under The MIT License.
* [http://www.opensource.org/licenses/mit-license.php]
*/

//****************************************************************************
// ActionScript Standard Library
// flash.geom.Rectangle object
//****************************************************************************

import flash7.geom.Point;

class flash7.geom.Rectangle
{
    public var x:Number = 0;
    public var y:Number = 0;
    public var width:Number = 0;
    public var height:Number = 0;
    
    public function get left():Number
    {
        return x;
    }
    public function set left( value:Number ):Void
    {
        width += x - value;
        x = value;
    }
    
    public function get right():Number
    {
        return x + width;
    }
    public function set right( value:Number ):Void
    {
        width = value - x;
    }
    
    public function get top():Number
    {
        return y;
    }
    public function set top( value:Number ):Void
    {
        height += y - value;
        y = value;
    }
    
    public function get bottom():Number
    {
        return y + height;
    }
    public function set bottom( value:Number ):Void
    {
        height = value - y;
    }
    
    public function get topLeft():Point
    {
        return new Point( x , y );
    }
    public function set topLeft( value:Point ):Void
    {
        top  = value.y;
        left = value.x;
    }
    
    public function get bottomRight():Point
    {
        return new Point( x + width , y + height );
    }
    public function set bottomRight( value:Point ):Void
    {
        bottom = value.y;
        right  = value.x;
    }
    
    public function get size():Point
    {
        return new Point( width , height );
    }
    public function set size( value:Point ):Void
    {
        width  = value.x;
        height = value.y;
    }
    
    public function Rectangle( x:Number, y:Number, width:Number, height:Number )
    {
        this.x      = ( isNaN(x)      ) ? 0 : x;
        this.y      = ( isNaN(y)      ) ? 0 : y;
        this.width  = ( isNaN(width)  ) ? 0 : width;
        this.height = ( isNaN(height) ) ? 0 : height;
    }
    
    public function clone():Rectangle
    {
        return new Rectangle( x , y , width , height );
    }
    
    public function isEmpty():Boolean
    {
        return ( width<=0 && height<=0 );
    }
    
    public function setEmpty():Void
    {
        x = y = width = height = 0;
    }
    
    public function inflate( dx:Number, dy:Number ):Void
    {
        x -= dx;
        y -= dy;
        width  += dx;
        height += dy;
    }
    
    public function inflatePoint( pt:Point ):Void
    {
        x -= pt.x;
        y -= pt.y;
        width  += pt.x;
        height += pt.y;
    }
    
    public function offset( dx:Number, dy:Number ):Void
    {
        x += dx;
        y += dy;
    }
    
    public function offsetPoint( pt:Point ):Void
    {
        x += pt.x;
        y += pt.y;
    }
    
    public function contains( x:Number, y:Number ):Boolean
    {
        var f:Boolean = ( this.x <= x && this.x + this.width >= x );
        f = ( this.y <= y && this.y + this.height >= y && f );
        return f;
    }
    
    public function containsPoint( pt:Point ):Boolean
    {
        var x:Number = pt.x;
        var y:Number = pt.y;
        var f:Boolean = ( this.x <= x && this.x + this.width >= x );
        f = ( this.y <= y && this.y + this.height >= y && f );
        return f;
    }
    
    public function containsRectangle( rect:Rectangle ):Boolean
    {
        var rx:Number = rect.x;
        var ry:Number = rect.y;
        var rw:Number = rx + rect.width;
        var rh:Number = ry + rect.height;
        var f:Boolean = true;
        f = ( this.x <= rx && this.x + this.width  >= rx && f );
        f = ( this.y <= ry && this.y + this.height >= ry && f );
        f = ( this.x <= rw && this.x + this.width  >= rw && f );
        f = ( this.y <= rh && this.y + this.height >= rh && f );
        return f;
    }
    
    public function intersection( toIntersect:Rectangle ):Rectangle
    {
        var nx:Number = 0, ny:Number = 0;
        var nw:Number = 0, nh:Number = 0;
        var ix:Number = toIntersect.x;
        var iy:Number = toIntersect.y;
        var iw:Number = ( toIntersect.width  <= 0 )? 0 : ix + toIntersect.width;
        var ih:Number = ( toIntersect.height <= 0 )? 0 : iy + toIntersect.height;
        var r:Number  = ( width<=0 ) ? 0 : x + width;
        var b:Number  = ( height<=0 )? 0 : y + height;
        
        if      ( x  <= ix && r  >= ix ) nx = ix;
        else if ( ix <= x  && iw >= x  ) nx = x;
        if      ( y  <= iy && b  >= iy ) ny = iy;
        else if ( iy <= y  && ih >= y  ) ny = y;
        if      ( x  <= iw && r  >= iw ) nw = iw - nx;
        else if ( ix <= r  && iw >= r  ) nw = r  - nx;
        if      ( y  <= ih && b  >= ih ) nh = ih - ny;
        else if ( iy <= b  && ih >= b  ) nh = b  - ny;
        
        if ( nw==0 || nh==0 ) {
            return new Rectangle(0,0,0,0);
        }
        return new Rectangle( nx, ny, nw, nh );
    }
    
    public function intersects( toIntersect:Rectangle ):Boolean
    {
        return !intersection( toIntersect ).isEmpty();
    }
    
    public function union( toUnion:Rectangle ):Rectangle
    {
        var ux:Number = toUnion.x;
        var uy:Number = toUnion.y;
        var uw:Number = ( toUnion.width  <= 0 )? 0 : ux + toUnion.width;
        var uh:Number = ( toUnion.height <= 0 )? 0 : uy + toUnion.height;
        var r:Number  = ( width<=0 ) ? 0 : x + width;
        var b:Number  = ( height<=0 )? 0 : y + height;
        var nx:Number = ( ux < x ) ? ux : x;
        var ny:Number = ( uy < y ) ? uy : y;
        var nw:Number = ( uw > r ) ? uw : r;
        var nh:Number = ( uh > b ) ? uh : b;
        return new Rectangle( nx, ny, nw, nh );
    }
    
    public function equals( toCompare:Object ):Boolean
    {
        var f:Boolean = true;
        f = ( x      == toCompare.x      && f );
        f = ( y      == toCompare.y      && f );
        f = ( width  == toCompare.width  && f );
        f = ( height == toCompare.height && f );
        return f;
    }
    
    public function toString():String
    {
        return "(x="+ x +", y="+ y +", w="+ width +", h="+ height +")";
    }
    
}